package com.steven.download.utils;

import android.content.Context;
import android.content.res.AssetManager;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.steven.download.AppConstant;
import com.steven.download.MainActivity;
import com.steven.download.download.UnZipCallback;
import com.steven.download.download.db.room.AppDataBase;
import com.steven.download.entity.JsonPathEntity;
import com.steven.download.entity.UninstallEntity;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * @Des:
 * @Author: hwz
 * @Date:2021/11/9 0009
 * @Version: 1.0
 */
public class ZipFileUtils {

    private static String TAG = "ZipFileUtils";


    /**
     * 解压下载得ZIP文件包
     *
     * @param zipPtath           需要解压得文件
     * @param outputDirectory    电子书解压到那个目录得地址
     * @param imgOutputDirectory 图片解压到那个目录得地址
     * @throws IOException
     */
    public static void unzipFile(String zipPtath, String outputDirectory,
                                 String imgOutputDirectory, String jsonOutputDirectory,
                                 UnZipCallback unZipCallback) {
        Log.i(TAG, "开始解压的文件： " + zipPtath + "\n" + "解压的目标路径：" + outputDirectory);
        // 创建解压目标目录
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    File file = new File(outputDirectory);
                    File imgfile = new File(imgOutputDirectory);
                    File jsonfile = new File(jsonOutputDirectory);
                    // 如果目标目录不存在，则创建
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    if (!imgfile.exists()) {
                        imgfile.mkdirs();
                    }

                    if (!jsonfile.exists()) {
                        jsonfile.mkdirs();
                    }

                    // 打开压缩文件
                    InputStream inputStream = new FileInputStream(zipPtath);

                    ZipInputStream zipInputStream = new ZipInputStream(inputStream);

                    // 读取一个进入点
                    ZipEntry zipEntry = zipInputStream.getNextEntry();
                    // 使用1Mbuffer
                    byte[] buffer = new byte[1024 * 1024];
                    // 解压时字节计数
                    int count = 0;
                    // 如果进入点为空说明已经遍历完所有压缩包中文件和目录
                    while (zipEntry != null) {
                        Log.i(TAG, "解压文件 入口 1： " + zipEntry);
                        if (!zipEntry.isDirectory()) {  //如果是一个文件
                            // 如果是文件
                            String fileName = zipEntry.getName();
                            Log.i(TAG, "解压文件 原来 文件的位置： " + fileName);
                            fileName = fileName.substring(fileName.lastIndexOf("/") + 1);  //截取文件的名字 去掉原文件夹名字
                            Log.i(TAG, "解压文件 的名字： " + fileName);
                            boolean isPic = fileName.contains(".jpg") || fileName.contains(".png");
                            boolean isJson = fileName.contains(".json");
                            if (isPic) {
                                imgfile = new File(imgOutputDirectory + File.separator + fileName);  //放到新的解压的文件路径
                                imgfile.createNewFile();
                            } else if (isJson) {
                                jsonfile = new File(jsonOutputDirectory + File.separator + fileName);  //放到新的解压的文件路径
                                jsonfile.createNewFile();
                                AppDataBase.getInstance(Utils.getContext()).getUninstallDao()
                                        .insert(new JsonPathEntity(jsonfile.getPath(),zipPtath));
                            } else {
                                if (fileName.contains("?")) {
                                    fileName = fileName.substring(0, fileName.lastIndexOf("?"));
                                }
                                file = new File(outputDirectory + File.separator + fileName);  //放到新的解压的文件路径
                                file.createNewFile();
                            }
                            FileOutputStream fileOutputStream = new FileOutputStream(isPic ? imgfile : isJson ? jsonfile : file);
                            while ((count = zipInputStream.read(buffer)) > 0) {
                                fileOutputStream.write(buffer, 0, count);
                            }
                            fileOutputStream.close();
                        }
                        // 定位到下一个文件入口
                        zipEntry = zipInputStream.getNextEntry();
                        Log.i(TAG, "解压文件 入口 2： " + zipEntry);
                    }
                    zipInputStream.close();
                    UIThreadUtil.runUITask(new Runnable() {
                        @Override
                        public void run() {
                            if (unZipCallback != null) {
                                unZipCallback.onSuccess(zipPtath);
                            }
                        }
                    });
                    Log.i(TAG, "解压完成");
                } catch (Exception e) {
                    Log.e(TAG, "解压失败"+e.getMessage()+zipPtath);
                    if (unZipCallback != null) {
                        unZipCallback.onFailure(e);
                    }
                }
            }
        }).start();
    }


    /**
     * 删除废弃的资源
     * @param zipPath
     */
    public static void deleteUnInstalFile(String zipPath){
        JsonPathEntity jsonPathEntity =
                AppDataBase.getInstance(Utils.getContext())
                        .getUninstallDao().queryJsonByPath(zipPath);
        if (jsonPathEntity != null && !TextUtils.isEmpty(jsonPathEntity.getPath())){
            List<UninstallEntity> uninstallEntities = ZipFileUtils.getJson(jsonPathEntity.getPath());
            if (uninstallEntities != null && uninstallEntities.size() > 0){
                for (UninstallEntity u : uninstallEntities) {
                    String name = u.getEbookFile();
                    String delDir = "";
                    if (name.contains(".jpg")){
                        delDir = AppConstant.IMG_UNZIP_DIR+name;
                    }else if (name.contains(".epub")){
                        delDir = AppConstant.BOOK_UNZIP_DIR+name.substring(u.getEbookFile().lastIndexOf("/")
                                ,u.getEbookFile().lastIndexOf("?"));
                    }
                    Log.e(TAG,"删除资源的路径："+delDir);
                    deleteSingleFile(delDir);
                }
                Log.e(TAG,"删除解压json文件："+jsonPathEntity.getPath());
                deleteSingleFile(jsonPathEntity.getPath());
                Log.e(TAG,"删除解压zip文件："+jsonPathEntity.getZipPath());
                deleteSingleFile(jsonPathEntity.getZipPath());
            }
        }
    }

    /**
     * 得到json文件中的内容
     *
     * @param fileName
     * @return
     */
    public static List<UninstallEntity> getJson(String fileName) {
        try {
            FileInputStream inputStream = new FileInputStream(fileName);
            // 调用
            String json = fileToStr(inputStream);
            Gson gson = new Gson();
           List<UninstallEntity>  fromJson = gson.fromJson(json,
                   new TypeToken<List<UninstallEntity>>(){}.getType());
           return fromJson;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String fileToStr(InputStream inputStream) throws IOException {
        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        // 数组长度
        byte[] buffer = new byte[1024];
        // 初始长度
        int len = 0;
        // 循环
        while ((len = inputStream.read(buffer)) != -1) {
            arrayOutputStream.write(buffer, 0, len);
//            return arrayOutputStream.toString();
        }
        Log.i(TAG, arrayOutputStream.toString());
        return arrayOutputStream.toString();
    }

    /** 删除文件，可以是文件或文件夹
     * @param delFile 要删除的文件夹或文件名
     * @return 删除成功返回true，否则返回false
     */
    public static boolean delete(String delFile) {
        File file = new File(delFile);
        if (!file.exists()) {
//            Toast.makeText(HnUiUtils.getContext(), "删除文件失败:" + delFile + "不存在！", Toast.LENGTH_SHORT).show();
            Log.e(TAG,"删除文件失败:" + delFile + "不存在！");
            return false;
        } else {
            if (file.isFile())
                return deleteSingleFile(delFile);
            else
                return deleteDirectory(delFile);
        }
    }

    /** 删除单个文件
     * @param filePath$Name 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteSingleFile(String filePath$Name) {
        File file = new File(filePath$Name);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                Log.e(TAG, "Copy_Delete.deleteSingleFile: 删除单个文件" + filePath$Name + "成功！");
                return true;
            } else {
                Log.e(TAG,"删除单个文件" + filePath$Name + "失败！");
                return false;
            }
        } else {
            Log.e(TAG,"删除单个文件失败：" + filePath$Name + "不存在！");
            return false;
        }
    }

    /** 删除目录及目录下的文件
     * @param filePath 要删除的目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String filePath) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!filePath.endsWith(File.separator))
            filePath = filePath + File.separator;
        File dirFile = new File(filePath);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            Log.e(TAG,"删除目录失败：" + filePath + "不存在！");
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (File file : files) {
            // 删除子文件
            if (file.isFile()) {
                flag = deleteSingleFile(file.getAbsolutePath());
                if (!flag)
                    break;
            }
            // 删除子目录
            else if (file.isDirectory()) {
                flag = deleteDirectory(file
                        .getAbsolutePath());
                if (!flag)
                    break;
            }
        }
        if (!flag) {
            Log.e(TAG,"删除目录失败！");
            return false;
        }
        // 删除当前目录
        if (dirFile.delete()) {
            Log.e(TAG, "Copy_Delete.deleteDirectory: 删除目录" + filePath + "成功！");
            return true;
        } else {
            Log.e(TAG,"删除目录：" + filePath + "失败！");
            return false;
        }
    }
}
